﻿using Azure.Core;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using seejee_Backendium.Core.Interfaces;
using seejee_Backendium.Core.Models;
using seejee_Backendium.Data.DbContest;
using seejee_Backendium.Data.Services;
using System.ComponentModel.DataAnnotations;
using System.Drawing.Printing;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using static Microsoft.Extensions.Logging.EventSource.LoggingEventSource;

namespace seejee_Backendium.WEB.Controllers
{
    [ApiController]
    [Route("api/")]
    public class OperatorController : ControllerBase
    {
        private readonly IOperatorService _operatorService;
        private readonly ApplicationDbContext _context;
        private readonly IConfiguration _configuration; // 新增字段
        private readonly ILogger<OperatorController> _logger;

        public OperatorController(IOperatorService operatorService, IConfiguration configuration, ILogger<OperatorController> logger, ApplicationDbContext context)
        {
            _operatorService = operatorService;
            _configuration = configuration;
            _logger = logger; // 
            _context = context; // 注入 ApplicationDbContext
        }
        // 登录接口
        [AllowAnonymous] // 登录接口允许匿名访问
        [HttpPost("operator/login")]
        public IActionResult Login([FromBody] LoginRequest request)
        {
            var loginResult = _operatorService.ValidateOperator(request.cOperatorName, request.cOperatorPassword, request.forceLogin);
            if (loginResult.IsSuccess)
            {
                // 生成 JWT Token
                var claims = new[]
                {
            new Claim(ClaimTypes.Name, request.cOperatorName)
        };
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"] ?? "your-very-strong-key"));
                var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

                var token = new JwtSecurityToken(
                    issuer: _configuration["Jwt:Issuer"] ?? "your-app",
                    audience: null,
                    claims: claims,
                    //expires: DateTime.Now.AddHours(1), // token有效期为1小时
                    expires: DateTime.Now.AddMinutes(10), // token有效期为10分钟

                    signingCredentials: creds);

                var tokenString = new JwtSecurityTokenHandler().WriteToken(token);

                //调用Token存储方法
                bool saveTokenResult = _operatorService.SaveToken(request.cOperatorName, tokenString);
                if (!saveTokenResult)
                {
                    _logger.LogError("Token存储失败，操作员名：{cOperatorName}", request.cOperatorName);
                    return StatusCode(500, new { success = false, message = "服务器错误，登录失败" });
                }
                // 返回成功信息（包含Token和提示消息）
                return Ok(new
                {
                    success = true,
                    token = tokenString,
                    message = loginResult.Message, // 如"登录成功"或"已强制登录"
                    isAlreadyOnline = loginResult.IsAlreadyOnline // 告知前端是否是强制登录
                });
            }
            else
            {
                // 2. 登录失败（区分"已在线需确认"和其他错误）
                return Ok(new
                {
                    success = false,
                    isAlreadyOnline = loginResult.IsAlreadyOnline, // 关键：标记是否已在线
                    message = loginResult.Message, // 具体错误信息（如"密码错误"、"已在线，是否继续登录？"）
                                                   // 不返回Token（登录失败）
                });
            }
        }
        public class LoginRequest
        {
            public string cOperatorName { get; set; }
            public string cOperatorPassword { get; set; }
            public bool forceLogin { get; set; }
        }
        // 操作员BI看板登录接口
        [AllowAnonymous] // 登录接口允许匿名访问
        [HttpPost("operator/BI/login")]
        public IActionResult Login([FromBody] BILoginRequest request)
        {
            var loginResult = _operatorService.ValidateBIOperator(request.cOperatorName, request.cOperatorPassword, request.forceLogin);
            if (loginResult.IsSuccess)
            {
                // 生成 JWT Token
                var claims = new[]
                {
            new Claim(ClaimTypes.Name, request.cOperatorName)
        };
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"] ?? "your-very-strong-key"));
                var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

                var token = new JwtSecurityToken(
                    issuer: _configuration["Jwt:Issuer"] ?? "your-app",
                    audience: null,
                    claims: claims,
                    //expires: DateTime.Now.AddHours(1), // token有效期为1小时
                    expires: DateTime.Now.AddMinutes(10), // token有效期为10分钟

                    signingCredentials: creds);

                var tokenString = new JwtSecurityTokenHandler().WriteToken(token);

                //调用Token存储方法
                bool saveTokenResult = _operatorService.SaveToken(request.cOperatorName, tokenString);
                if (!saveTokenResult)
                {
                    _logger.LogError("Token存储失败，操作员名：{cOperatorName}", request.cOperatorName);
                    return StatusCode(500, new { success = false, message = "服务器错误，登录失败" });
                }
                // 返回成功信息（包含Token和提示消息）
                return Ok(new
                {
                    success = true,
                    token = tokenString,
                    message = loginResult.Message, // 如"登录成功"或"已强制登录"
                    isAlreadyOnline = loginResult.IsAlreadyOnline // 告知前端是否是强制登录
                });
            }
            else
            {
                // 2. 登录失败（区分"已在线需确认"和其他错误）
                return Ok(new
                {
                    success = false,
                    isAlreadyOnline = loginResult.IsAlreadyOnline, // 关键：标记是否已在线
                    message = loginResult.Message, // 具体错误信息（如"密码错误"、"已在线，是否继续登录？"）
                                                   // 不返回Token（登录失败）
                });
            }
        }
        public class BILoginRequest
        {
            public string cOperatorName { get; set; }
            public string cOperatorPassword { get; set; }
            public bool forceLogin { get; set; }
        }
        //自动续期token接口,传入旧token，返回新token
        [Authorize]
        [HttpPost("token/refresh")]
        public IActionResult RefreshToken([FromBody] TokenRefreshRequest request)
        {
            try
            {
                var handler = new JwtSecurityTokenHandler();
                var token = handler.ReadJwtToken(request.Token);
                // 获取用户名
                var operatorName = token.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value;
                if (string.IsNullOrEmpty(operatorName))
                {
                    return BadRequest(new { success = false, message = "无效的Token" });
                }
                // 生成新的Token
                var claims = new[]
                {
                    new Claim(ClaimTypes.Name, operatorName)
                };
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"] ?? "your-very-strong-key"));
                var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
                var newToken = new JwtSecurityToken(
                    issuer: _configuration["Jwt:Issuer"] ?? "your-app",
                    audience: null,
                    claims: claims,
                    //expires: DateTime.Now.AddHours(1), // token有效期为1小时
                    expires: DateTime.Now.AddMinutes(10), // token有效期为10分钟
                    signingCredentials: creds);
                var tokenString = handler.WriteToken(newToken);
                var lastTime = _operatorService.UpdateLastTime(request.cOperatorName);
                //调用Token存储方法
                bool saveTokenResult = _operatorService.SaveToken(request.cOperatorName, tokenString);
                if (!saveTokenResult)
                {
                    _logger.LogError("Token存储失败，操作员名：{cOperatorName}", request.cOperatorName);
                    return StatusCode(500, new { success = false, message = "服务器错误，登录失败" });
                }
                return Ok(new { success = true, token = tokenString });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Token续期失败");
                return StatusCode(500, new { success = false, message = "服务器错误" });
            }
        }
        public class TokenRefreshRequest
        {
            public string cOperatorName { get; set; }
            public string Token { get; set; }
        }

        // 获取操作员列表
        [HttpGet("operator/list")]
        public IActionResult GetAllOperator([FromQuery] int pageIndex, [FromQuery] int pageSize, [FromQuery] string keyword = "")
        {
            if (pageIndex < 1 || pageSize < 1)
            {
                return BadRequest(new { success = false, message = "参数错误" });
            }
            try
            {
                var operators = _operatorService.GetAllOperator(pageIndex, pageSize, keyword);
                return Ok(new { success = true, data = operators });
            }
            catch (Exception ex)
            {
                // 可选：记录日志
                return StatusCode(500, new { success = false, message = ex.Message });
            }

        }
        //修改密码
        [HttpPut("operator/setpassword")]
        public IActionResult UpdatePassword([FromBody] OperatorPasswordDTO operatorUpdatePassword)
        {
            try
            {
                var result = _operatorService.UpdatePassword(operatorUpdatePassword);
                if (result)
                    return Ok(new { Success = true, Message = "密码修改成功" });
                return StatusCode(500, new { Success = false, Message = "密码修改失败" });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "密码修改失败");
                return StatusCode(500, new { Success = false, Message = "服务器错误" });
            }
        }

        //旧密码，新密码，验证后修改密码
        [Authorize]
        [HttpPut("operator/updateOldPassword")]
        public IActionResult UpdateOldPassword([FromBody] OperatorOldPasswordDTO request)
        {
            try
            {
                var result = _operatorService.UpdateOldPassword(request.oldPassword, request.newPassword, request.cOperatorName);
                if (result)
                    return Ok(new { Success = true, Message = "密码修改成功" });
                return StatusCode(500, new { Success = false, Message = "密码修改失败" });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "密码修改失败");
                return StatusCode(500, new { Success = false, Message = "服务器错误" });
            }
        }
        public class OperatorOldPasswordDTO
        {
            public string oldPassword { get; set; }
            public string newPassword { get; set; }
            public string cOperatorName { get; set; }
        }
        //添加操作员
        [HttpPost("operator/insert")]
        public async Task<IActionResult> InsertOperator([FromBody] OperatorInsertDTO user)
        {
            //  生成随机盐值 
            //var salt = PasswordService.GenerateSalt();
            //Console.WriteLine(salt);
            //生成固定盐值
            //var salt = PasswordService.GenerateSalt();

            //  二次哈希处理 
            var finalHash = PasswordService.HashPassword(user.cOperatorPassword, user.Salt);

            //  创建操作员实体
            var operators = new OperatorInsertDTO
            {
                cOperatorName = user.cOperatorName,
                cOperatorRealName = user.cOperatorRealName,
                cOperatorPassword = finalHash,
                iOperatorPermissions = user.iOperatorPermissions,
                //cOperatorUserKey = user.cOperatorUserKey,
                //cOperatorLicenses = user.cOperatorLicenses,
                //dOperatorExpiryDate = user.dOperatorExpiryDate,
                // 使用生成的盐值
                Salt = user.Salt,
                //dOperatorCreateTime = DateTime.UtcNow
                dOperatorCreateTime = user.dOperatorCreateTime
                //dOperatorCreateTime = user.dOperatorCreateTime
            };
            var result = _operatorService.InsertOperator(operators);
            if (result)
                return Ok(new { Success = true, Message = "操作员添加成功" });
            return StatusCode(500, new { Success = false, Message = "操作员添加失败" });
        }

        // 操作员名唯一性校验接口
        [HttpGet("operator/check-operatorname")]
        public async Task<IActionResult> CheckUsernameUnique([FromQuery] string cOperatorName, [FromQuery] int? excludeId = null)
        {
            //// 基础校验 
            //if (string.IsNullOrWhiteSpace(username))
            //    return BadRequest(new { error = "操作员名不能为空" });

            //if (username.Length < 3 || username.Length > 20)
            //    return BadRequest(new { error = "操作员名长度需在3-20字符之间" });

            // 数据库查询 [[1]][[6]]
            try
            {
                bool exists;
                if (excludeId.HasValue)
                {
                    // 编辑场景：排除当前操作员ID对应的记录
                    exists = await _context.OperatorNameDTOs
                        .AnyAsync(u => u.cOperatorName == cOperatorName
                                    && u.iOperatorID != excludeId.Value);
                }
                else
                {
                    // 新增场景：直接检查是否存在该用户名
                    exists = await _context.OperatorNameDTOs
                        .AnyAsync(u => u.cOperatorName == cOperatorName);
                }

                //bool exists = await _context.UserNameDTOs
                //    .AnyAsync(u => u.cOperatorName == cOperatorName);
                //bool exists = await _context.OperatorNameDTOs.AnyAsync(u => u.cOperatorName == cOperatorName);
                return Ok(new { exists });
            }
            catch (Exception ex)
            {
                // 记录日志
                _logger.LogError(ex, "操作员名校验失败");
                return StatusCode(500, new { error = "服务器内部错误" });
            }
        }
        //修改操作员信息
        [HttpPut("operator/update/{id}")]
        public IActionResult UpdateOperator([FromBody] UpdateOperatorDTO user)
        {
            try
            {
                var result = _operatorService.UpdateOperator(user);
                if (result)
                    return Ok(new { Success = true, Message = "操作员信息更新成功" });
                return StatusCode(500, new { Success = false, Message = "操作员信息更新失败" });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "操作员信息更新失败");
                return StatusCode(500, new { Success = false, Message = "服务器错误" });
            }
        }
        // 删除操作员
        [HttpDelete("operator/delete/{cOperatorName}")]
        public IActionResult DeleteOperator(string cOperatorName)
        {
            try
            {
                var result = _operatorService.DeleteOperator(cOperatorName);
                if (result)
                    return Ok(new { Success = true, Message = "操作员删除成功" });
                return StatusCode(500, new { Success = false, Message = "操作员删除失败" });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "操作员删除失败");
                return StatusCode(500, new { Success = false, Message = "服务器错误" });
            }
        }
        //退出登录
        [Authorize] // 必须登录（有效Token）才能调用
        [HttpPost("operator/logout")] // 接口路径与前端一致
        public IActionResult Logout()
        {
            try
            {
                // 1. 从JWT Token中获取当前登录用户名（登录时已存入ClaimTypes.Name）
                var operatorName = User.FindFirstValue(ClaimTypes.Name);
                if (string.IsNullOrWhiteSpace(operatorName))
                {
                    _logger.LogWarning("退出登录失败：无法从Token中获取用户名");
                    return Unauthorized(new { Success = false, Message = "身份验证失效，请重新登录" });
                }
                var tokenString = "NULL";
                // 2. 调用Service更新在线状态为离线（false）
                bool updateResult = _operatorService.UpdateOperatorOnlineStatus(operatorName, false);
                //调用Token存储方法
                bool saveTokenResult = _operatorService.SaveToken(operatorName, tokenString);

                if (updateResult)
                {
                    if (!saveTokenResult)
                    {
                        _logger.LogError("Token存储失败，操作员名：{operatorName}", operatorName);
                        return StatusCode(500, new { success = false, message = "服务器错误，登录失败" });
                    }
                    return Ok(new { Success = true, Message = "退出登录成功，在线状态已更新" });
                }
                else
                {
                    // 操作员不存在或更新失败
                    return BadRequest(new { Success = false, Message = "更新在线状态失败，操作员不存在或系统异常" });
                }

            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "退出登录接口发生异常");
                return StatusCode(500, new { Success = false, Message = "服务器内部错误，退出失败" });
            }
        }
        //上传base64首页logo到数据库
        [Authorize]
        [HttpPost("system/setHomeImage")]
        public IActionResult UploadLogo([FromBody] LogoUploadRequest request)
        {
            if (string.IsNullOrWhiteSpace(request.Base64Image))
            {
                return BadRequest(new { Success = false, Message = "图像数据不能为空" });
            }
            try
            {
                _operatorService.SaveImage(request.Base64Image, request.cOperatorName);
                return Ok(new { Success = true, Message = "Logo上传成功" });
            }
            catch (Exception ex)
            {
                // 记录日志
                _logger.LogError(ex, "上传Logo失败");
                return StatusCode(500, new { Success = false, Message = "服务器错误，上传失败" });
            }
        }

        //获取数据库中的base64首页logo
        [HttpGet("system/getHomeImage")]
        public IActionResult GetLogo([FromQuery] LogoGetRequest request)
        {
            try
            {
                var base64Image = _operatorService.GetImage(request.cOperatorName);
                if (string.IsNullOrWhiteSpace(base64Image))
                {
                    return NotFound(new { Success = false, Message = "未找到Logo图像" });
                }
                return Ok(new { Success = true, Data = base64Image });
            }
            catch (Exception ex)
            {
                // 记录日志
                _logger.LogError(ex, "获取Logo失败");
                return StatusCode(500, new { Success = false, Message = "服务器错误，获取失败" });
            }
        }
        public class LogoUploadRequest
        {

            public string Base64Image { get; set; }
            public string cOperatorName { get; set; }
        }
        public class LogoGetRequest
        {
            public string cOperatorName { get; set; }
        }
        [HttpPut("operator/state/{iOperatorID:int}")] // 改用Put方法更符合语义
        public async Task<IActionResult> UpdateAccState(
        [FromRoute, Range(1, int.MaxValue)] int iOperatorID,
        [FromBody] UserStateUpdateDto dto)
        {
            // 1. 模型验证（如果在Dto中定义了数据注解，这里会自动验证）
            if (!ModelState.IsValid)
            {
                _logger.LogWarning("修改数据源记录（cid：{0}）：模型验证失败", iOperatorID);
                return BadRequest(ModelState);
            }

            // 2. 校验cid一致性
            if (iOperatorID != dto.iOperatorID)
            {
                _logger.LogWarning("修改数据源记录：路由cid[{0}]与请求体cid[{1}]不一致", iOperatorID, dto.iOperatorID);
                return BadRequest("路由中的cid必须与请求体中的cid一致");
            }
            try
            {

                // 4. 调用服务层修改
                var isSuccess = _operatorService.UpdateStateAsync(iOperatorID, dto.state);
                if (!isSuccess)
                {
                    _logger.LogError("修改数据源记录失败（iOperatorID：{0}）", iOperatorID);
                    return BadRequest("修改失败：未找到匹配记录或数据无变化");
                }

                return NoContent();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "修改数据源记录失败（iOperatorID：{0}）", iOperatorID);
                return StatusCode(500, "服务器内部错误：修改数据失败");
            }
        }
    }

}
